#ifndef _CIRCLE_DUAL_LINK_LIST_H_
#define _CIRCLE_DUAL_LINK_LIST_H_

#include "DualLinkList.h"

namespace MySTL
{

template < typename T >
class CircleDualLinkList : public DualLinkList<T>
{
public:
	~CircleDualLinkList();

	bool insert(int n, const T& value);
	bool insert(const T& value);
	bool remove(int n);
	bool get(int n, T& value) const;
	T& get(int n);
	const T& get(int n) const;
	bool set(int n, const T& value);
	void clear();

	T& operator [](int n);
	const T& operator [](int n) const;

	bool move(int n, int step = 1);

protected:
	typedef typename DualLinkList<T>::Node Node;
	int mod(int n) const;
	void last_to_first();
};

template < typename T >
CircleDualLinkList<T>::~CircleDualLinkList()
{
	clear();
}

template < typename T >
bool CircleDualLinkList<T>::insert(int n, const T& value)
{
	n = this->m_length > 0 ? n % (this->m_length + 1) : 0;

	bool ret = DualLinkList<T>::insert(n, value);

	if (ret && n == 0)
	{
		last_to_first();
	}

	return ret;
}

template < typename T >
bool CircleDualLinkList<T>::insert(const T& value)
{
	return insert(this->m_length, value);
}

template < typename T >
bool CircleDualLinkList<T>::remove(int n)
{
	n = mod(n);

	bool ret = (n >= 0) && (n < this->m_length);

	if (ret)
	{
		if (n == 0)
		{
			Node* current = this->position(n);
			Node* toDel = current->next;

			if (toDel->next != toDel)
			{
				current->next = toDel->next;
				toDel->next->pre = toDel->pre;

				if (this->m_current == toDel)
				{
					this->m_current = toDel->next;
				}

				last_to_first();
			}
			else
			{
				current->next = NULL;
				current->pre = NULL;
				this->m_current = NULL;
			}

			--this->m_length;

			this->destory_node(toDel);
		}
		else
		{
			ret = DualLinkList<T>::remove(n);
		}
	}

	return ret;
}

template < typename T >
bool CircleDualLinkList<T>::get(int n, T& value) const
{
	return DualLinkList<T>::get(mod(n), value);
}

template < typename T >
T& CircleDualLinkList<T>::get(int n)
{
	return DualLinkList<T>::get(mod(n));
}

template < typename T >
const T& CircleDualLinkList<T>::get(int n) const
{
	return DualLinkList<T>::get(mod(n));
}

template < typename T >
bool CircleDualLinkList<T>::set(int n, const T& value)
{
	return DualLinkList<T>::set(mod(n), value);
}

template < typename T >
void CircleDualLinkList<T>::clear()
{
	while (this->m_length > 1)
	{
		remove(1);
	}

	if (this->m_length == 1)
	{
		remove(0);
	}
}

template < typename T >
T& CircleDualLinkList<T>::operator [](int n)
{
	return DualLinkList<T>::operator [](mod(n));
}

template < typename T >
const T& CircleDualLinkList<T>::operator [](int n) const
{
	return DualLinkList<T>::operator [](mod(n));
}

template < typename T >
bool CircleDualLinkList<T>::move(int n, int step)
{
	return DualLinkList<T>::move(mod(n), step);
}

template < typename T >
int CircleDualLinkList<T>::mod(int n) const
{
	return this->m_length > 0 ? n % this->m_length : 0;
}

template < typename T >
void CircleDualLinkList<T>::last_to_first()
{
	Node* last = this->m_header.pre;
	Node* first = this->m_header.next;

	if (NULL != last)
	{
		last->next = first;
		first->pre = last;
	}
}

}

#endif